/*! \file CommandLine.cpp
 *	\brief
 *
 *	created:	2010/12/17
 *	created:	17:12:2010   14:00
 *	filename: 	c:\src\tactics-engine\libs\utils\CommandLine.cpp
 *	file path:	c:\src\tactics-engine\libs\utils
 *	file base:	CommandLine
 *	file ext:	cpp
 *	author:		VennGrayDog
 *				VennGrayDog@gmail.com
 */
#include "utils/stdafx.h"
#include "utils/CommandLine.h"

namespace tt{
namespace utils{

#if defined(TT_UNIX)
#   define strcpy_s strcpy
#   define strcat_s strcat

Char* DoGetCommandLineA()
{
    FILE* file = fopen("/proc/self/cmdline", "r");
    if(!file)
        return NULL;

    static Char s_commandLine[PATH_MAX] = {0};
    Size readed = fread(s_commandLine, sizeof(Char), PATH_MAX, file);
    s_commandLine[readed] = 0;

    fclose(file);

    return s_commandLine;
}

Char* GetCommandLineA()
{
    static Char* s_commandLine = DoGetCommandLineA();
    return s_commandLine;
}

#endif //defined(TT_UNIX)

CommandLine::CommandLine()
: m_parameters()
{

}

CommandLine::~CommandLine()
{

}

void CommandLine::Init( const Char* commandLine )
{
	value_type key;
	value_type value;

	const Char* current_pos = commandLine;
	while(*current_pos)
	{
		key = getToken(&current_pos);
		if (!isKeyName(key))
		{
			m_parameters[key] = value_type();
			continue;
		}

		for (;;)
		{
			key.erase(0,1);

			if (!*current_pos)
			{
				m_parameters[key] = value_type();
				break;
			}

			value = getToken(&current_pos);
			if(isKeyName(value))
			{
				m_parameters[key] = value_type();
				key = value;
			}
			else
			{
				m_parameters[key] = value;
				break;
			}
		}
	}
}

void CommandLine::InitFromStd()
{
	InitFromStdWithAdditionalParams(NULL);
}

void CommandLine::InitFromStdWithAdditionalParams( const Char* additionalParams )
{
	Char commandLine[1024] = {0};
	strcpy_s(commandLine, GetCommandLineA());
	if (additionalParams)
	{
		strcat_s(commandLine, " ");
		strcat_s(commandLine, additionalParams);
	}
	Init(commandLine);
}

bool CommandLine::IsPresent( const Char* key )
{
	return m_parameters.find(key) != m_parameters.end();
}

void CommandLine::GetString( const Char* key, value_type& value )
{
	Parameters::const_iterator it = m_parameters.find(key);
	if(it != m_parameters.end())
		value = it->second;
}

void CommandLine::GetUInt( const Char* key, unsigned int& value )
{
	Parameters::const_iterator it = m_parameters.find(key);
	if(it != m_parameters.end())
	{
		value = atoi( it->second.c_str() );
	}
}

//////////////////////////////////////////////////////////////////////////
std::string CommandLine::getToken( const Char** current_pos_p )
{
	const Char*& current_pos = *current_pos_p;
	const Char* tokenBegin = current_pos;
	const Char* tokenEnd = current_pos;

	while(*current_pos && isspace(*current_pos))
		current_pos++;
	if(!*current_pos)
		return std::string();

	if(*current_pos == '"')
	{
		++tokenBegin;
		++current_pos;
		while(*current_pos && *current_pos != '"') ++current_pos;
		if (*current_pos)
		{
			tokenEnd = current_pos - 1;
			++current_pos;
		}
		else
		{
			tokenEnd = current_pos;
		}
	}
	else
	{
		while(*current_pos && !isspace(*current_pos)) ++current_pos;
		tokenEnd = current_pos;
	}

	while(*current_pos && isspace(*current_pos))
		current_pos++;

//	*current_pos_p = current_pos;
	return std::string(tokenBegin, tokenEnd);
}

bool CommandLine::isKeyName( const std::string& key )
{
	if (key.empty())
		return false;
	if(key[0] == '-')
		return true;
	if(key[0] == '/')
		return true;
	return false;
}

} //namespace utils
} //namespace tt

